package org.summerframework.component.security.core.interceptor;

import org.summerframework.component.security.context.RequestContextFactory;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * 初始化requestContext
 *
 * @author 石超
 * @version v1.0.0
 */
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestContextInterceptor extends AbstractContextHandlerInterceptorAdapter {

    @Setter
    private String jsonContentType = MediaType.APPLICATION_JSON_VALUE;

    private final static ThreadLocal<Boolean> BOOLEAN_THREAD_LOCAL = ThreadLocal.withInitial(() -> false);

    @Autowired(required = false)
    private ServletContext servletContext;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (BOOLEAN_THREAD_LOCAL.get()) {
            log.trace("已经创建Context");
            return true;
        }

        if (response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS) == null) {
            String origin = request.getHeader(HttpHeaders.ORIGIN);
            response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, StringUtils.isNotBlank(origin) ? origin : "*");
            response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
            response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Accept,content-type,cache-control,x-requested-with,X_Requested_With,authorization,authentication,x-xsrf-token,expose-headers");
            response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, DELETE, PUT, OPTIONS");
            response.addHeader(HttpHeaders.ALLOW, "GET, POST, DELETE, PUT, OPTIONS");
        }

        RequestContextFactory.initRequestContext(request, response, servletContext);
        BOOLEAN_THREAD_LOCAL.set(true);

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;

        if (!isHtml(handlerMethod)) {
            response.addHeader(HttpHeaders.CONTENT_TYPE, jsonContentType);
        }


        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        getContext().setTimeout(System.currentTimeMillis());
        BOOLEAN_THREAD_LOCAL.remove();
        RequestContextFactory.clean();
    }
}
